package gui;

import java.util.LinkedList;

/*a classe transforma Strings(informadas pelo usuario) em objects.
 * Essas strings serao os valores para as entradas de um metodo que o usuario irah fornecer
 * ou pode ser um valor para uma saida de um metodo que o usuario irah fornecer*/
public class InstanciaEntradasESaidasDeUmMetodo 
{
	
	/*dado um valor para um parametro de entrada em String, 
	 * esse valor sera convertido para um objeto com o mesmo tipo de tipoDeUmParametro.
	 * A funcao tb funciona para converter retornos esperados*/
	public static Object converterValorDoParametroEmObjeto(Class tipoDeUmParametro,
					String valorParaEsteParametro) throws ValorInvalidoParaParametroException
	{
		if(ChecaTipoDeClasse.classeEhString(tipoDeUmParametro) == true)
		{
			return valorParaEsteParametro;
		}
		else if(ChecaTipoDeClasse.classeEhBoolean(tipoDeUmParametro) == true)
		{
			try
			{
				boolean valorEmBooleano = Boolean.valueOf(valorParaEsteParametro);
				return valorEmBooleano;
			}
			catch(Exception e)
			{
				/*se der algum erro na conversao da string para objeto, eh porque o usuario
				 * informou um valor invalida para o parametro do metodo. O metodo nao poderah
				 * ser invocado com este valor dado como entrada*/
				throw new ValorInvalidoParaParametroException();
			}
		}
		else if(ChecaTipoDeClasse.classeEhByte(tipoDeUmParametro) == true)
		{
			try
			{
				byte valorEmByte = Byte.valueOf(valorParaEsteParametro);
				return valorEmByte;
			}
			catch(Exception e)
			{
				throw new ValorInvalidoParaParametroException();
			}
		}
		else if(ChecaTipoDeClasse.classeEhChar(tipoDeUmParametro) == true)
		{
			try
			{
				char valorEmChar = valorParaEsteParametro.charAt(0);
				return valorEmChar;
			}
			catch(Exception e)
			{
				throw new ValorInvalidoParaParametroException();
			}
		}
		else if(ChecaTipoDeClasse.classeEhDouble(tipoDeUmParametro) == true)
		{
			try
			{
				Double valorEmDouble = Double.valueOf(valorParaEsteParametro);
				return valorEmDouble;
			}
			catch(Exception e)
			{
				throw new ValorInvalidoParaParametroException();
			}
		}
		else if(ChecaTipoDeClasse.classeEhFloat(tipoDeUmParametro) == true)
		{
			try
			{
				Float valorEmFloat = Float.valueOf(valorParaEsteParametro);
				return valorEmFloat;
			}
			catch(Exception e)
			{
				throw new ValorInvalidoParaParametroException();
			}
		}
		else if(ChecaTipoDeClasse.classeEhInteiro(tipoDeUmParametro) == true)
		{
			try
			{
				int valorEmInt = Integer.valueOf(valorParaEsteParametro);
				return valorEmInt;
			}
			catch(Exception e)
			{
				throw new ValorInvalidoParaParametroException();
			}
		}
		else if(ChecaTipoDeClasse.classeEhLong(tipoDeUmParametro) == true)
		{
			try
			{
				Long valorEmLong = Long.valueOf(valorParaEsteParametro);
				return valorEmLong;
			}
			catch(Exception e)
			{
				throw new ValorInvalidoParaParametroException();
			}
		}
		else if(ChecaTipoDeClasse.classeEhShort(tipoDeUmParametro) == true)
		{
			try
			{
				Short valorEmShort = Short.valueOf(valorParaEsteParametro);
				return valorEmShort;
			}
			catch(Exception e)
			{
				throw new ValorInvalidoParaParametroException();
			}
		}
		else
		{
			throw new ValorInvalidoParaParametroException(); //tambem nao trataremos tipos nao primitivos
		}
	}
	
	public static LinkedList<Object> instanciarVariosParametrosDeEntrada
									(DeclaracaoDeMetodo declaracaoDeMetodo,
										LinkedList<String> valoresParaParametrosDeEntrada)
	{
		LinkedList<Object> parametrosDeEntradaInstanciados = new LinkedList<Object>();
		Class[] tiposDosParametrosDeEntrada =
				declaracaoDeMetodo.getTiposDosParametrosDeEntrada();
		
		for(int i = 0; i < valoresParaParametrosDeEntrada.size(); i++)
		{
			String umValorParaUmParametroDeEntrada = valoresParaParametrosDeEntrada.get(i);
			Class tipoParaOValorDoParametroDeEntrada = tiposDosParametrosDeEntrada[i];
			try
			{
				Object instanciaDoParametroDeEntrada = 
						converterValorDoParametroEmObjeto(tipoParaOValorDoParametroDeEntrada,
															umValorParaUmParametroDeEntrada);
				
				parametrosDeEntradaInstanciados.add(instanciaDoParametroDeEntrada);
			}
			catch(ValorInvalidoParaParametroException e)
			{
				//se alguem informou algum parametro invalido entao nao ha como instanciar os parametros de entrada
				return null;
			}
		}
		
		/*se terminou o loop e nenhum valor invalido foi encontrado, 
		 * entao podemos instanciar os parametros de entrada normalmente*/
		return parametrosDeEntradaInstanciados;
	}
	
	public static Object instanciarSaidaEsperada(DeclaracaoDeMetodo declaracaoDoMetodo,
																String valorParaEsteRetorno)
	{
		try
		{
			Class tipoDoRetorno = declaracaoDoMetodo.getTipoDeRetorno();
			Object instanciaDoRetorno = 
					converterValorDoParametroEmObjeto(tipoDoRetorno, valorParaEsteRetorno);
			return instanciaDoRetorno;
		}
		catch(ValorInvalidoParaParametroException e)
		{
			//se alguem informou algum retorno invalido entao nao ha como instanciar o retorno
			return null;
		}
	}
}
